package com.gengzp.system.service.impl;

import com.gengzp.common.enums.ServiceFrontBackTypeEnum;
import com.gengzp.common.exception.BusinessException;
import com.gengzp.common.model.pagination.resp.PaginationResponse;
import com.gengzp.common.model.serviceGovernance.dto.ServiceHealthyInstanceDto;
import com.gengzp.common.model.serviceGovernance.entity.ServiceGovernance;
import com.gengzp.common.model.serviceGovernance.req.CreateServiceGovernanceReq;
import com.gengzp.common.model.serviceGovernance.req.EditServiceGovernanceReq;
import com.gengzp.common.model.serviceGovernance.req.PageServiceGovernanceReq;
import com.gengzp.common.model.serviceGovernance.resp.PageServiceGovernanceResp;
import com.gengzp.common.model.serviceGovernance.resp.SearchServiceGovernanceResp;
import com.gengzp.common.model.user.entity.SysUser;
import com.gengzp.common.utils.ThreadUtils;
import com.gengzp.rpc.model.serviceRegistration.resp.SearchServiceRegistrationResp;
import com.gengzp.rpc.utils.RpcUtils;
import com.gengzp.system.facade.SysUserFacade;
import com.gengzp.system.mapper.ServiceGovernanceMapper;
import com.gengzp.system.service.ServiceGovernanceService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @ClassName ServiceGovernanceServiceImpl
 * @Description 服务治理模块服务层实现类
 * @Author gengzp
 * @Date 2025/10/14 10:38
 */
@Service
public class ServiceGovernanceServiceImpl implements ServiceGovernanceService {

    @Autowired
    private ServiceGovernanceMapper serviceGovernanceMapper;

    @Autowired
    private SysUserFacade sysUserFacade;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createServiceGovernance(CreateServiceGovernanceReq req) {
        AtomicReference<SysUser> projectManager = new AtomicReference<>();
        List<String> errorMessages = ThreadUtils.batchExecute(() -> {
            if (Objects.nonNull(serviceGovernanceMapper.selectServiceGovernanceByServiceName(req.getServiceName()))) {
                throw BusinessException.get(String.format("服务名【%s】已存在", req.getServiceName()));
            }
        }, () -> {
            if (Objects.nonNull(serviceGovernanceMapper.selectServiceGovernanceByServiceTitle(req.getServiceTitle()))) {
                throw BusinessException.get(String.format("服务标题【%s】已存在", req.getServiceTitle()));
            }
        }, () -> {
            SysUser sysUser = sysUserFacade.searchSysUserByNickname(req.getProjectManagerNickname());
            if (Objects.isNull(sysUser)) {
                throw BusinessException.get(String.format("项目管理员昵称【%s】不存在", req.getProjectManagerNickname()));
            }
            projectManager.set(sysUser);
        });
        if (CollectionUtils.isNotEmpty(errorMessages)) {
            throw BusinessException.get(String.join("；", errorMessages));
        }

        ServiceGovernance serviceGovernance = new ServiceGovernance();
        serviceGovernance.setServiceName(req.getServiceName());
        serviceGovernance.setServiceTitle(req.getServiceTitle());
        serviceGovernance.setServiceDescription(req.getServiceDescription());
        serviceGovernance.setServiceConfigFile(req.getServiceConfigFile());
        serviceGovernance.setFrontBackType(req.getFrontBackType());
        serviceGovernance.setGitUrl(req.getGitUrl());
        serviceGovernance.setProjectManager(String.valueOf(projectManager.get().getId()));
        serviceGovernanceMapper.insertServiceGovernance(serviceGovernance);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editServiceGovernanceById(EditServiceGovernanceReq req) {
        AtomicReference<SysUser> projectManager = new AtomicReference<>();
        List<String> errorMessages = ThreadUtils.batchExecute(() -> {
            ServiceGovernance existServiceGovernance = serviceGovernanceMapper
                    .selectServiceGovernanceByServiceTitle(req.getServiceTitle());
            if (Objects.nonNull(existServiceGovernance) && !Objects.equals(req.getId(), String.valueOf(existServiceGovernance.getId()))) {
                throw BusinessException.get(String.format("服务标题【%s】已存在", req.getServiceTitle()));
            }
        }, () -> {
            ServiceGovernance existServiceGovernance = serviceGovernanceMapper
                    .selectServiceGovernanceByServiceName(req.getServiceName());
            if (Objects.nonNull(existServiceGovernance) && !Objects.equals(req.getId(), String.valueOf(existServiceGovernance.getId()))) {
                throw BusinessException.get(String.format("服务名【%s】已存在", req.getServiceName()));
            }
        }, () -> {
            SysUser sysUser = sysUserFacade.searchSysUserByNickname(req.getProjectManagerNickname());
            if (Objects.isNull(sysUser)) {
                throw BusinessException.get(String.format("项目管理员昵称【%s】不存在", req.getProjectManagerNickname()));
            }
            projectManager.set(sysUser);
        });
        if (CollectionUtils.isNotEmpty(errorMessages)) {
            throw BusinessException.get(String.join("；", errorMessages));
        }

        ServiceGovernance serviceGovernance = serviceGovernanceMapper.selectServiceGovernanceById(Long.valueOf(req.getId()));
        if (Objects.isNull(serviceGovernance)) {
            throw BusinessException.get("当前服务治理信息不存在");
        }

        serviceGovernance.setServiceName(req.getServiceName());
        serviceGovernance.setServiceTitle(req.getServiceTitle());
        serviceGovernance.setServiceDescription(req.getServiceDescription());
        serviceGovernance.setServiceConfigFile(req.getServiceConfigFile());
        serviceGovernance.setFrontBackType(req.getFrontBackType());
        serviceGovernance.setGitUrl(req.getGitUrl());
        serviceGovernance.setProjectManager(String.valueOf(projectManager.get().getId()));
        serviceGovernanceMapper.updateServiceGovernanceById(serviceGovernance);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeServiceGovernanceById(Long serviceGovernanceId) {
        serviceGovernanceMapper.deleteServiceGovernanceById(serviceGovernanceId);
    }

    @Override
    public PaginationResponse<PageServiceGovernanceResp> pageQueryServiceGovernance(PageServiceGovernanceReq req) {
        List<ServiceGovernance> serviceGovernanceList = serviceGovernanceMapper.pageQueryServiceGovernance(req);
        if (CollectionUtils.isEmpty(serviceGovernanceList)) {
            return PaginationResponse.get(Lists.newArrayList(), req);
        }

        // 所有关联的用户id
        Set<Long> userIds = Sets.newHashSet();

        // 分页查询返回结果
        List<PageServiceGovernanceResp> results = Lists.newArrayList();
        for (ServiceGovernance serviceGovernance : serviceGovernanceList) {
            PageServiceGovernanceResp resp = new PageServiceGovernanceResp();
            resp.setId(String.valueOf(serviceGovernance.getId()));
            resp.setServiceName(serviceGovernance.getServiceName());
            resp.setServiceTitle(serviceGovernance.getServiceTitle());
            resp.setServiceDescription(serviceGovernance.getServiceDescription());
            resp.setFrontBackType(serviceGovernance.getFrontBackType());
            resp.setFrontBackTypeValue(ServiceFrontBackTypeEnum.getValueByCode(serviceGovernance.getFrontBackType()));
            resp.setProjectManager(serviceGovernance.getProjectManager());
            resp.setCreatedBy(String.valueOf(serviceGovernance.getCreatedBy()));
            resp.setCreatedTime(serviceGovernance.getCreatedTime());
            resp.setLastModifiedBy(String.valueOf(serviceGovernance.getLastModifiedBy()));
            resp.setLastModifiedTime(serviceGovernance.getLastModifiedTime());
            results.add(resp);

            // 将关联的用户id全部收集到集合中, 用于后续拼接数据
            userIds.add(serviceGovernance.getCreatedBy());
            userIds.add(serviceGovernance.getLastModifiedBy());
            userIds.add(Long.valueOf(serviceGovernance.getProjectManager()));
        }

        // 查询所有关联的用户id对应昵称映射
        Map<Long, String> userId2NicknameMap = Optional.ofNullable(
                        sysUserFacade.searchSysUserId2NicknameMapByIds(userIds))
                .orElse(Maps.newHashMap());
        for (PageServiceGovernanceResp result : results) {
            result.setCreatedByUserNickname(userId2NicknameMap.getOrDefault(Long.valueOf(result.getCreatedBy()),
                    "该用户已不存在"));
            result.setLastModifiedByUserNickname(userId2NicknameMap.getOrDefault(Long.valueOf(result.getLastModifiedBy()),
                    "该用户已不存在"));
            result.setProjectManagerNickname(userId2NicknameMap.getOrDefault(Long.valueOf(result.getProjectManager()),
                    "该用户已不存在"));

            // 使用 Rpc 框架的服务注册功能获取健康实例数
            result.setHealthyInstanceCount(Optional.of(
                            RpcUtils.getAllServiceRegistrationInformationByServiceName(result.getServiceName()).size())
                    .orElse(0));
        }

        return PaginationResponse.get(results, req);
    }

    @Override
    public SearchServiceGovernanceResp searchServiceGovernanceById(Long serviceGovernanceId) {
        ServiceGovernance serviceGovernance = serviceGovernanceMapper.selectServiceGovernanceById(serviceGovernanceId);
        if (Objects.isNull(serviceGovernance)) {
            throw BusinessException.get("当前服务治理信息不存在");
        }

        SearchServiceGovernanceResp resp = new SearchServiceGovernanceResp();
        resp.setId(String.valueOf(serviceGovernance.getId()));
        resp.setServiceName(serviceGovernance.getServiceName());
        resp.setServiceTitle(serviceGovernance.getServiceTitle());
        resp.setServiceDescription(serviceGovernance.getServiceDescription());
        resp.setServiceConfigFile(serviceGovernance.getServiceConfigFile());
        resp.setFrontBackType(serviceGovernance.getFrontBackType());
        resp.setFrontBackTypeValue(ServiceFrontBackTypeEnum.getValueByCode(serviceGovernance.getFrontBackType()));
        resp.setGitUrl(serviceGovernance.getGitUrl());
        resp.setProjectManager(serviceGovernance.getProjectManager());
        resp.setCreatedBy(String.valueOf(serviceGovernance.getCreatedBy()));
        resp.setCreatedTime(serviceGovernance.getCreatedTime());
        resp.setLastModifiedBy(String.valueOf(serviceGovernance.getLastModifiedBy()));
        resp.setLastModifiedTime(serviceGovernance.getLastModifiedTime());
        resp.setServiceHealthyInstances(Lists.newArrayList());

        // 根据关联的用户id查询id昵称映射, 拼接用户信息
        Map<Long, String> userId2NicknameMap = Optional.ofNullable(sysUserFacade.searchSysUserId2NicknameMapByIds(Arrays.asList(
                        serviceGovernance.getCreatedBy(), serviceGovernance.getLastModifiedBy(), Long.valueOf(serviceGovernance.getProjectManager()))))
                .orElse(Maps.newHashMap());
        resp.setCreatedByUserNickname(userId2NicknameMap.getOrDefault(Long.valueOf(resp.getCreatedBy()), "该用户已不存在"));
        resp.setLastModifiedByUserNickname(userId2NicknameMap.getOrDefault(Long.valueOf(resp.getLastModifiedBy()), "该用户已不存在"));
        resp.setProjectManagerNickname(userId2NicknameMap.getOrDefault(Long.valueOf(resp.getProjectManager()), "该用户已不存在"));

        // 组装健康实例信息
        List<SearchServiceRegistrationResp> healthyInstances = RpcUtils
                .getAllServiceRegistrationInformationByServiceName(serviceGovernance.getServiceName());
        if (CollectionUtils.isNotEmpty(healthyInstances)) {
            for (SearchServiceRegistrationResp healthyInstance : healthyInstances) {
                ServiceHealthyInstanceDto healthyInstanceDto = new ServiceHealthyInstanceDto();
                healthyInstanceDto.setServiceAddress(healthyInstance.getAddress());
                healthyInstanceDto.setRegisterIpType(healthyInstance.getRegisterIpType());
                resp.getServiceHealthyInstances().add(healthyInstanceDto);
            }
        }

        return resp;
    }

}
